﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using AllInOnePluginBL.Helpers;
using PluginDB;

namespace AllInOnePluginBL.SiteScrappers
{
    /// <summary>
    /// Summary description for BaseSiteParserJob
    /// </summary>
    public class MyVodTVParserJob : BaseSiteScrapper
    {
        #region Private Members
        private const string DEFAULT_URL = "http://www.myvod.tv/";
        private const string NAME = "MyVod.tv";
        #endregion

        #region Ctor
        public MyVodTVParserJob() : base(NAME)
        {
        } 
        #endregion

        #region Implementation of IJob
        public override void Execute(int pagesToScan)
        {
            _log.Info(string.Format("Start Executing MyVodTVParserJob at {0}", DateTime.Now.ToString("r")));

            var lastPageNumber = GetLastPageLink(DEFAULT_URL);
            pagesToScan = (pagesToScan == 0 || pagesToScan > lastPageNumber) ? lastPageNumber : pagesToScan;

            for (var i = pagesToScan; i > 0; i--)
            {
                var url = string.Format("{0}page/{1}", DEFAULT_URL, i);
                this.GetMovies(url);
            }

            _log.Info(string.Format("End Executing MyVodTVParserJob at {0}", DateTime.Now.ToString("r")));
        }
        #endregion

        #region Private Methods
        private void GetMovies(string url)
        {
            try
            {
                string page;
                try
                {
                    page = Utils.GetPage(url, Encoding.UTF8);
                }
                catch (Exception)
                {
                    page = Utils.GetPage(url, Encoding.UTF8);
                }

                const string moviesContainerExpression =
                    "<div class=\"window\">.*?><a href=\"(.+?)\".*?title=\"(.+?)\".*?><img src=\"(.+?)\".*?/>";
                var exp = new Regex(moviesContainerExpression, RegexOptions.Singleline);
                var matches = exp.Matches(page);
                foreach (Match match in matches)
                {
                    try
                    {
                        var moviePageLink = match.Groups[1].Value;
                        var movieTitle = match.Groups[2].Value;

                        if (_pluginDBHandler.IsVideoExists(moviePageLink))
                            continue;

                        var video = FillMovieInfo(movieTitle, moviePageLink);

                        if (video.Links.Count == 0)
                        {
                            _log.Warn("{0} Has no links. not saving it", movieTitle);
                            continue;
                        }

                        _pluginDBHandler.AddNewVideo(video);
                    }
                    catch (Exception ex)
                    {
                        _log.ErrorException(string.Format("Error in MyVodParser::Get Movie. moviePageLink:{0}", match.Groups[1].Value), ex);
                    }
                }
            }
            catch (Exception ex)
            {
                _log.ErrorException(string.Format("Error in MyVodParser::GetMovies. url:{0}", url), ex);
            }
        }

        private PluginVideoInfo FillMovieInfo(string movieName, string moviePageLink)
        {
            var pageContent = Utils.GetPage(moviePageLink, Encoding.UTF8);

            #region Get Plot and Image
            string plot, imageUrl;
            GetPlotAndImage(pageContent, out plot, out imageUrl);
            #endregion

            var video = new PluginVideoInfo
            {
                VideoName = movieName,
                PluginUrl = moviePageLink,
                SiteName = NAME,
                Categories = GetCategoriesNames(pageContent),
                ImageUrl = imageUrl
            };

            #region Get Links
            var links = Utils.GetMovieLinks(pageContent);
            foreach (var link in links)
            {
                video.Links.Add(new PluginVideoInfo.Link
                {
                    LinkURL = link,
                    SourceName = GetLinkSource(link)
                });
            }
            return video;
            #endregion
        }

        private void GetPlotAndImage(string pageContent, out string plot, out string image)
        {
            try
            {
                const string moviePlotExpression = "<div id=\"related\">(.+?)<a href";
                var matches = Regex.Matches(pageContent, moviePlotExpression, RegexOptions.Singleline);
                foreach (Match match in matches)
                {
                    const string exp = "<img src=\"(.+?)\".*?/>(.+?)[a href][<ofer>]";
                    var match1 = Regex.Match(match.Groups[1].Value + "<ofer>", exp, RegexOptions.Singleline);
                    if (match1.Success)
                    {
                        image = match1.Groups[1].Value.Trim();
                        plot = match1.Groups[2].Value.Trim();
                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception in GetPlotAndImage: {0}", ex.Message);
            }
            plot = string.Empty;
            image = string.Empty;
        }

        private List<string> GetCategoriesNames(string pageContent)
        {
            var categoriesList = new List<string>();
            const string expression = "<h5>עוד באותה קטגוריה:(.*?)</h5>";
            var match = Regex.Match(pageContent, expression, RegexOptions.Singleline);
            if (match.Success)
            {
                var cleanResult = match.Groups[1].Value.
                                    Replace("\r", string.Empty).
                                    Replace("\n", string.Empty).
                                    Replace(",", ";").Trim();
                var categories = cleanResult.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
                categoriesList.AddRange(categories.Select(category => category.Trim()));
            }

            return categoriesList;
        }

        private string GetLinkSource(string link)
        {
            const string expression = @"^([a-zA-Z]+:\/\/)?([^\/]+)\/.*?$";
            var match = Regex.Match(link, expression, RegexOptions.Singleline);
            if (match.Success)
            {
                var list = match.Groups[2].Value.Split('.');
                if (list[0] == "www")
                    return list[1];
                return list[0];

            }
            return string.Empty;
        }

        private int GetLastPageLink(string baseUrl)
        {
            try
            {
                var url = string.Format("{0}page/{1}", baseUrl, 1);
                var pageContent = Utils.GetPage(Utils.LoopDecodeUrl(url), Encoding.UTF8);

                const string moviePlotExpression = "class=\"wp-pagenavi\">.*?<span class=\"current\">.*?</span><a href.*?</a><a href.*?</a>.*?<a href=\"(.+?)\".*?>.*?</div>";
                var exp = new Regex(moviePlotExpression, RegexOptions.Singleline);
                var match = exp.Match(pageContent);
                if (match.Success)
                {
                    var urlFormat = string.Format("{0}page/", baseUrl);
                    var pageNumber = match.Groups[1].Value.Trim().Replace(urlFormat, string.Empty);
                    return int.Parse(pageNumber);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception in GetLastPageLink: {0}", ex.Message);
            }

            return 0;
        }
        #endregion
    }
}